precision highp float;
//glsllib
#define VERSION1 1
#import "Common/ShaderLib/Lighting.glsllib"
uniform vec4 g_LightData[NB_LIGHTS];
float fresnelReflectance( vec3 H, vec3 V, float F0 ) {
    float base = 1.0 - dot( V, H );
    float exponential = pow( base, 5.0 );
    return exponential + F0 * ( 1.0 - exponential );
}
float KS_Skin_Specular( sampler2D tBeckmann, vec3 N,vec3 L,vec3 V,float m,float rho_s) {
    float result = 0.0;
    float ndotl = dot( N, L );
    if( ndotl > 0.0 ) {
            vec3 h = L + V;
            vec3 H = normalize( h );
            float ndoth = dot( N, H );
            float PH = pow( 2.0 * texture2D( tBeckmann, vec2( ndoth, m ) ).x, 10.0 );
            float F = fresnelReflectance( H, V, 0.028 );
            float frSpec = max( PH * F / dot( h, h ), 0.0 );
            result = ndotl * rho_s * frSpec;
    }
    return result;
}
const float NORMAL_TYPE = -1.0f;
void main() {
    vec3 outgoingLight = vec3( 0.0 );
    vec4 diffuseColor = vec4( diffuse, opacity );
    vec4 mSpecular = vec4( specular, opacity );
    vec4 colDiffuse = texture2D( tDiffuse, iTexCoords );
    colDiffuse *= colDiffuse;
    diffuseColor *= colDiffuse;
    
    //vec4 posAndU = vec4( -vViewPosition, iTexCoords.x );
    //vec4 posAndU_dx = dFdx( posAndU ),  posAndU_dy = dFdy( posAndU );
    //vec3 tangent = posAndU_dx.w * posAndU_dx.xyz + posAndU_dy.w * posAndU_dy.xyz;
    //vec3 normal = normalize( iNormal );
    //vec3 binormal = normalize( cross( tangent, normal ) );
    //tangent = cross( normal, binormal );
    //mat3 tsb = mat3( tangent, binormal, normal );
    //vec3 normalTex = texture2D( uNormalMap, iTexCoords ).xyz * 2.0 - 1.0;
    //normalTex.xy *= uNormalScale;
    //normalTex = normalize( normalTex );
    //vec3 finalNormal = tsb * normalTex;
    //normal = normalize( finalNormal );
    
    vec3 norm = normalize(iNormal);
    vec3 tan = normalize(iTangent.xyz);
    mat3 tbnMat = mat3(tan, iTangent.w * cross( (norm), (tan)), norm);
    vec4 normalHeight = texture2D(uNormalMap, iTexCoords);
    //normalHeight.xy *= uNormalScale;
    vec3 normal = normalize((normalHeight.xyz * vec3(2.0f, NORMAL_TYPE * 2.0f, 2.0f) - vec3(1.0f, NORMAL_TYPE * 1.0f, 1.0f)));
    normal.xy *= uNormalScale;
    normal = normalize(normal);
    normal = normalize(tbnMat * normal);
    
    vec3 viewerDirection = normalize( vViewPosition );
    vec3 totalDiffuseLight = vec3( 0.0 );
    vec3 totalSpecularLight = vec3( 0.0 );
    #if NUM_POINT_LIGHTS > 0
            for ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {
                    vec3 pointVector = normalize( pointLights[ i ].direction );
                    float attenuation = calcLightAttenuation( length( lVector ), pointLights[ i ].distance, pointLights[ i ].decay );
                    float pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );
                    totalDiffuseLight += pointLightColor[ i ] * ( pointDiffuseWeight * attenuation );
                    if ( passID == 1 ) {
                            float pointSpecularWeight = KS_Skin_Specular( tBeckmann, normal, pointVector, viewerDirection, uRoughness, uSpecularBrightness );
                            totalSpecularLight += pointLightColor[ i ] * mSpecular.xyz * ( pointSpecularWeight * attenuation );
                    }
            }
    #endif
    #if NUM_DIR_LIGHTS > 0
            for( int i = 0; i < NUM_DIR_LIGHTS; i++ ) {
                    vec3 dirVector = directionalLights[ i ].direction;
                    float dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );
                    totalDiffuseLight += directionalLights[ i ].color * dirDiffuseWeight;
                    if ( passID == 1 ) {
                            float dirSpecularWeight = KS_Skin_Specular( tBeckmann, normal, dirVector, viewerDirection, uRoughness, uSpecularBrightness );
                            totalSpecularLight += directionalLights[ i ].color * mSpecular.xyz * dirSpecularWeight;
                    }
            }
    #endif
    vec3 dLights = vec3(.0f);
    for(int i = 0;i < NB_LIGHTS;i+=3){
        vec4 lightColor = g_LightData[i];            
        vec4 lightData1 = g_LightData[i+1];
        
        vec4 lightDir4;
        vec3 lightVec;
        lightComputeDir(iPosition, lightColor.w, lightData1, lightDir4, lightVec);
        
        float dirDiffuseWeight = max( dot( normal, lightDir4.xyz ), 0.0f );
        totalDiffuseLight += lightColor.xyz * dirDiffuseWeight;
        if ( passID == 1 ) {
            float dirSpecularWeight = KS_Skin_Specular( tBeckmann, normal, lightDir4.xyz, viewerDirection, uRoughness, uSpecularBrightness );
            totalSpecularLight += lightColor.xyz * mSpecular.xyz * dirSpecularWeight;
        }
        
        //vec3 L = normalize(lightData1.xyz - iPosition);
        
        //jme3 lib
        //float fallOff = 1.0f;
        //point light attenuation
        //fallOff *= lightDir4.w;
        //vec3 directDiffuse;
        //vec3 directSpecular;
        //PBR_ComputeDirectLight(normal, lightDir4.xyz, V,
        //                    lightColor.rgb,iSpecular, roughness, NoV,
        //                    directDiffuse,  directSpecular);
        //vec3 directLighting = diffuseColor.rgb *directDiffuse + directSpecular;
        //dLights             += directLighting * fallOff;
    }
    outgoingLight += diffuseColor.rgb * ( totalDiffuseLight + totalSpecularLight );
    if ( passID == 0 ) {
        outgoingLight = sqrt( outgoingLight );
        //outgoingLight = vec3(1.0f);
    } else if ( passID == 1 ) {
        #ifdef VERSION1
            vec3 nonblurColor = sqrt(outgoingLight );
        #else
            vec3 nonblurColor = outgoingLight;
        #endif
        vec3 blur1Color = texture2D( tBlur1, iTexCoords ).xyz;
        vec3 blur2Color = texture2D( tBlur2, iTexCoords ).xyz;
        vec3 blur3Color = texture2D( tBlur3, iTexCoords ).xyz;
        vec3 blur4Color = texture2D( tBlur4, iTexCoords ).xyz;
        outgoingLight = vec3( vec3( 0.22,  0.437, 0.635 ) * nonblurColor + 
        vec3( 0.101, 0.355, 0.365 ) * blur1Color + 
        vec3( 0.119, 0.208, 0.0 )   * blur2Color + 
        vec3( 0.114, 0.0,   0.0 )   * blur3Color + 
        vec3( 0.444, 0.0,   0.0 )   * blur4Color );
        outgoingLight *= sqrt( colDiffuse.xyz );
        outgoingLight += ambientLightColor * diffuse * colDiffuse.xyz + totalSpecularLight;
        //outgoingLight = blur2Color;
        #ifndef VERSION1
            outgoingLight = sqrt( outgoingLight );
        #endif
    }
    oColor = vec4( outgoingLight.rgb, diffuseColor.a );
}